/*
 * WildcardSqlSessionFactoryBean.java Copyright PrinceEgg Tech Co. Ltd. All Rights Reserved.
 */
package org.infohold.mysql.conf;


import java.io.IOException;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import com.google.common.collect.Sets;

import lombok.extern.slf4j.Slf4j;


/**
 * 提供typeAliasesPackage的通配符实现
 * 
 * @author kangLiu
 */
@Slf4j
public class WildcardSqlSessionFactoryBean extends SqlSessionFactoryBean {

    private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    @Override
    public void setTypeAliasesPackage(String typeAliasesPackage) {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
        typeAliasesPackage = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                             + ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/"
                             + DEFAULT_RESOURCE_PATTERN;

        // 将加载多个绝对匹配的所有Resource
        // 将首先通过ClassLoader.getResource("META-INF")加载非模式路径部分
        // 然后进行遍历模式匹配
        try {
            Set<String> result = Sets.newHashSet();
            Resource[] resources = resolver.getResources(typeAliasesPackage);
            if (resources != null && resources.length > 0) {
                MetadataReader metadataReader = null;
                for (Resource resource : resources) {
                    if (resource.isReadable()) {
                        metadataReader = metadataReaderFactory.getMetadataReader(resource);
                        try {
                            result.add(Class.forName(
                                metadataReader.getClassMetadata().getClassName()).getPackage().getName());
                        }
                        catch (ClassNotFoundException e) {}
                    }
                }
            }
            if (result.size() > 0) {
                super.setTypeAliasesPackage(StringUtils.join(result.toArray(), ","));
            }
            else {
                log.warn("参数typeAliasesPackage:" + typeAliasesPackage + "，未找到任何包");
            }
        }
        catch (IOException e) {
            log.error("解析typeAliasesPackage失败!", e);
        }
    }
}
